package com.mas.monitor;

import jade.core.Agent;
import jade.core.behaviours.TickerBehaviour;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Map;

import com.mas.common.AgentUtil;
import com.mas.common.Consts;
import com.mas.resource.ResourceAllocator;

public class TickerMonitorResources extends TickerBehaviour {
	
	Map resourcesCatalog;
	
	public TickerMonitorResources(Agent a, long period) {
		super(a, period);
		resourcesCatalog = ((MonitorResourceAgent)myAgent).getMapResourceAllocator();
	}

	protected void onTick() 
    {
		  try
		  {
			  AgentUtil.debug(myAgent, "ResourceMonitor-agent:onTick: receive data, Please Wait . . .");
			  Process p = Runtime.getRuntime().exec(Consts.MonitorExeFullPath);
			  //wait for termination of the exe, stuck till termination
			  p.waitFor();
			  AgentUtil.debug(myAgent,"ResourceMonitor-agent:onTick: Got data:\t");
			  //get exe standard output
			  BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); 
			  String currentLine = null;
			  String allLines = ""; 
			  while  (  ( currentLine = in.readLine (  )  )  != null )  
				  allLines += currentLine ;
			  AgentUtil.debug(myAgent,allLines);
			  
			  updateResourcesCatalog(allLines); 
			  printResourcesCatalog(); 
		  }
		  catch (Exception exc)
		  {
			  System.out.println("ResourceMonitor-agent: "+ myAgent.getAID().getName()+"exception while try run monitor exe" + exc.toString());
		  }
    }
	

	  
	  /**
	   *Get string with data about the resources.
	   *Analyzed the string and update the catalog 
	   */
	  private void updateResourcesCatalog(String newData)
	  {
		  if (newData == null)
			  return;
		  
		  double newValue,newAvgValue;
		  double oldValue,oldAvgValue;
		  String parts[] = newData.split(",");
		  int i=0;
		  
		  updateResource(Consts.RESOURCE_AMOUNT_TO_BUY, Double.parseDouble(parts[i++]),Consts.CPU_MaxAllocationValue);
		  updateResource(Consts.RESOURCE_START_TIME, Double.parseDouble(parts[i++]),Consts.MEM_MaxAllocationValue);
		  updateResource(Consts.RESOURCE_END_TIME,  Double.parseDouble(parts[i++]),Consts.HD_MaxAllocationValue);
		  updateResource(Consts.RESOURCE_NET, Double.parseDouble(parts[i++]),Consts.NET_MaxAllocationValue);
	  }

	  private void updateResource(String resourceName, double newValue, double maxAllocationValue)
	  {
		  double newAvgValue;
		  double oldAvgValue;
		  
		  oldAvgValue = ((ResourceAllocator)resourcesCatalog.get(resourceName)).getAvgResourceCurrentUsage();
		  double resourcePurchased = ((ResourceAllocator)resourcesCatalog.get(resourceName)).getResourcePurchased();
		  
		  if (oldAvgValue == -1.0) //first run
			  newAvgValue = newValue;
		  else
			  newAvgValue = (Consts.AVG_UPDATE_FACTOR * newValue)  + (  (1 - Consts.AVG_UPDATE_FACTOR) * oldAvgValue );
		  
		  if (resourceName == Consts.RESOURCE_END_TIME)
			  resourcesCatalog.put(resourceName, 
		  			   new ResourceAllocator(resourceName, 0 , 0 , newValue, resourcePurchased));			  
		  else
			  resourcesCatalog.put(resourceName, 
				  			   new ResourceAllocator(resourceName, newValue, newAvgValue , maxAllocationValue, resourcePurchased));
	  }
	  
	  private void printResourcesCatalog ()
	  {
		  if (resourcesCatalog != null)
		  AgentUtil.debug(myAgent,resourcesCatalog.toString());		 
	  }
	  
}
